﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WHControlLib.Controls
{
    public partial class WHListBox : ListBox
    {
        public WHListBox()
        {

            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // 双缓冲   
            this.SetStyle(ControlStyles.ResizeRedraw, true); // 调整大小时重绘
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景. 
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); // 开启控件透明

            ////背景定义为透明色   
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            BackColor = Color.Transparent;


            InitializeComponent();
       this.DrawMode = DrawMode.OwnerDrawFixed;
        }


        ////////////////////全局定义参数********************************
        ///
        Rectangle BackgroundRect=new Rectangle();
        Rectangle ItemFillRect=new Rectangle();
        Rectangle ItemDrawRect = new Rectangle();
 
        int LastMouseIndex = -1;
          int MouseIndex = -1;

        #region 公共属性定义区域
        public enum FillColorDec
        {
            Vertical,
            Horizontal,
            LeftVH,
            RightVH

        }

        private bool _isUseBackTransparent=true;
        [Category("A我的"), Description("是否启用背景透明，默认，是"), Browsable(true)]
        public bool IsUseBackTransparent
        {
            get { return _isUseBackTransparent; }
            set
            {
                if (value)
                {
                    BackColor = Color.Transparent;

                    Invalidate();
                }
                else { 
                 BackColor = _myBackColor;
                    Invalidate();
                }
               
                
                _isUseBackTransparent= value; }
        }

        private Color _myBackColor=Color.White;
        [Category("A我的"), Description("如果不起用透明色的时候的背景颜色，默认，白色"), Browsable(true)]
        public Color MyBackColor
        {
            get { return BackColor; }
            set   {
                _myBackColor = value;
                BackColor=_myBackColor;
                Invalidate();
            }
        }


        private Color _itemBackColor=Color.LightGoldenrodYellow;
        [Category("A单项设置"), Description("每一项的背景色，默认，深黄色"), Browsable(true)]
        public Color ItemBackColor
        {
            get { return _itemBackColor; }
            set { _itemBackColor= value; Invalidate(); }
        }
        private bool _isUseMouseOnColor=false;
        [Category("A我的"), Description("是否启用鼠标经过每一项变色，默认，是"), Browsable(true)]
        public bool IsUseMouseOnColor
        {
            get { return _isUseMouseOnColor; }
            set { _isUseMouseOnColor = value; Invalidate(); }
        }


        private Color _itemMouseOnColor=Color.YellowGreen;
        [Category("A单项设置"), Description("每一项鼠标经过时候的颜色，默认，黄绿色"), Browsable(true)]
        public Color ItemMouseOnColor
        {
            get { return _itemMouseOnColor; }
            set { _itemMouseOnColor = value; Invalidate(); }
        }

        private Color _itemSelectColor=Color.Blue;
        [Category("A单项设置"), Description("每一项选中后的颜色，默认，蓝色"), Browsable(true)]
        public Color ItemSelectColor
        {
            get { return _itemSelectColor; }
            set { _itemSelectColor = value; Invalidate(); }
        }
        private Color _itemTextColor=Color.Black;
        [Category("A单项设置"), Description("每一项字体的颜色，默认，黑色"), Browsable(true)]
        public Color ItemTextColor
        {
            get { return _itemTextColor; }
            set { _itemTextColor = value; Invalidate(); }
        }
        private Color _itemSelectedBorderColor=Color.Black;
        [Category("A单项设置"), Description("如果启用单项边框每一项选中时候的边框颜色，默认，黑色"), Browsable(true)]
        public Color ItemSelectedBorderColor
        {
            get { return _itemSelectedBorderColor; }
            set { _itemSelectedBorderColor = value; }
        }
        private Color _itemMouseOnBorderColor=Color.Red;
        [Category("A单项设置"), Description("如果启用单项边框每一项鼠标经过的边框颜色，默认，红色"), Browsable(true)]
        public Color ItemMouseOnBorderColor
        {
            get { return _itemMouseOnBorderColor; }
            set { _itemMouseOnBorderColor = value; }
        }

        public enum ItemTextDec
        {center,left,right

        }
        private ItemTextDec _myItemTextDec;
        [Category("A单项设置"), Description("每一项字体的显示位置，默认，center 中间"), Browsable(true)]
        public ItemTextDec MyItemTextDec
        {
            get { return _myItemTextDec; }
            set { _myItemTextDec = value; }
        }

     


        
        private bool _isShowItemBorder=true;
        [Category("A单项设置"), Description("是否显示每一项的边框，默认，true"), Browsable(true)]
        public bool IsShowItemBorder
        {
            get { return _isShowItemBorder; }
            set { _isShowItemBorder = value; }
        }
        public enum ItemBorderShape
        {
            RoundRectange,Rectange,TwoHalfCirclRectange
        }
        private ItemBorderShape _myItemBorderShape;
        [Category("A单项设置"), Description("是否显示每一项的边框的形状，默认，圆角矩形"), Browsable(true)]
        public ItemBorderShape MyItemBorderShape
        {
            get { return _myItemBorderShape; }
            set { _myItemBorderShape = value; }
        }
        private float _itemRadius=3.0f;
        [Category("A单项设置"), Description("每一项如果边框是圆角矩形的顶角的圆弧大小，默认，3.0f即每一项高的1/3"), Browsable(true)]
        public float ItemRadius
        {
            get { return _itemRadius; }
            set { _itemRadius = value; }
        }

        private int _itemBorderWidth = 2;
        [Category("A单项设置"), Description("每一项的边框宽度，默认，2"), Browsable(true)]
        public int ItemBorderWidth
        {
            get { return _itemBorderWidth; }
            set { _itemBorderWidth = value; }
        }
        private Color _itemBorderColor=Color.Green;
        [Category("A单项设置"), Description("每一项的边框的颜色，默认，绿色"), Browsable(true)]
        public Color ItemBorderColor
        {
            get { return _itemBorderColor; }
            set { _itemBorderColor = value; }
        }




        #endregion

        //protected override void WndProc(ref Message m)
        //{
        //    if (m.Msg == Win32Msg.WM_PAINT)
        //    {
        //        Graphics g = this.CreateGraphics();
        //        FillRectangeBackground(g, this.ClientRectangle);
        //        g.Dispose();
        //    }
        //    base.WndProc(ref m);

        //}


        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics gg = e.Graphics;
            gg.SmoothingMode = SmoothingMode.AntiAlias;
            gg.CompositingQuality = CompositingQuality.HighQuality;
            gg.InterpolationMode = InterpolationMode.HighQualityBicubic;
            if (Items.Count>0)
            {

           
               for (int i = 0; i < Items.Count; i++)
              {
                  Rectangle rct=GetItemRectangle(i);

                    if (rct != null)
                    {
                        if (SelectedItems.Contains(Items[i]))
                
                        {
                            FillItemBackColor(gg, rct, ItemSelectColor);


                            DrawMyItemText(gg, rct, i);

                            if (IsShowItemBorder)
                            {
                                DrawItemBorder(gg, rct, ItemSelectedBorderColor);
                            }

                        }
                        else
                        {
                            FillItemBackColor(gg, rct, ItemBackColor);

                            DrawMyItemText(gg, rct, i);
                            if (IsShowItemBorder)
                            {
                                DrawItemBorder(gg, rct, ItemBorderColor);
                            }
                        }


                    }


                }

              }
            }


     

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(e);
            Graphics Myg = e.Graphics;

            Myg.SmoothingMode = SmoothingMode.AntiAlias;
            Myg.CompositingQuality = CompositingQuality.HighQuality;
            Myg.InterpolationMode = InterpolationMode.HighQualityBicubic;
        
            BackgroundRect = this.ClientRectangle;
            if (Items==null)
            {
                return;
            }
            if (e.Index < 0)
            {
                return;
            }
            if (Items.Count <= 0)
            {
                return;

            }
            if (e.Index > Items.Count)
            {
                return;
            }

            //e.DrawBackground();


            Rectangle itemBorderRect = new Rectangle();
            itemBorderRect = e.Bounds;
         
            FillItemColor(Myg, e);

        
        
        }

        void FillItemColor(Graphics Myg,  DrawItemEventArgs e)
        {


          ItemFillRect= e.Bounds;
             ItemDrawRect = ItemFillRect;

            //e.DrawBackground();

            if (e.Index>-1)
            {

                if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
                    {
                    FillItemBackColor(Myg, ItemFillRect, ItemSelectColor);


                    DrawMyItemText(Myg, ItemFillRect, e.Index);

                    if (IsShowItemBorder)
                    {
                        DrawItemBorder(Myg, ItemDrawRect, ItemSelectedBorderColor);
                    }

                }
                else
                {
                    FillItemBackColor(Myg, ItemFillRect, ItemBackColor);
           
                    DrawMyItemText(Myg, ItemFillRect, e.Index);
                    if (IsShowItemBorder)
                    {
                        DrawItemBorder(Myg,ItemDrawRect, ItemBorderColor);
                    }
                }
                
              
            }


        }

      
          

                  
 
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (Items.Count<=0)
            {
                return;
            }
            else
            {
                  int index = this.IndexFromPoint(e.Location);
              if (IsUseMouseOnColor)
            {
               DrawMouseMoveFouces(index);
            }       
            }
       
       

        }
        /// <summary>
        /// 画随鼠标移动停留到的焦点项
        /// </summary>
        /// <param name="index">鼠标停留项的索引</param>
        private void DrawMouseMoveFouces(int itemindex)
        {
           Graphics g = this.CreateGraphics();
            g.SmoothingMode = SmoothingMode.AntiAlias;


            //当鼠标指针第一次进入控件时候

      
            if (LastMouseIndex < 0 && MouseIndex < 0 && itemindex > -1)
            {


                //确定 填充 和 画边框的路径
 
                  MouseIndex = itemindex;
           
                FillItemBackColor(g, GetItemRectangle(MouseIndex), ItemMouseOnColor);
                DrawMyItemText(g, GetItemRectangle(MouseIndex), MouseIndex);
                if (IsShowItemBorder)
                {
                    DrawItemBorder(g, GetItemRectangle(MouseIndex), ItemMouseOnBorderColor);


                }
                g.Dispose();
                return;
            }
            //******************************
            //当鼠标指针在各项间来回移动

            if (itemindex > -1 && itemindex != MouseIndex && MouseIndex != LastMouseIndex)
            {
                LastMouseIndex = MouseIndex;
                MouseIndex = itemindex;



                if (!SelectedIndices.Contains(LastMouseIndex))
                {
                    FillItemBackColor(g, GetItemRectangle(LastMouseIndex), ItemBackColor);
                  
                    DrawMyItemText(g, GetItemRectangle(LastMouseIndex), LastMouseIndex);
                    if (IsShowItemBorder)
                    {

                        DrawItemBorder(g, GetItemRectangle(LastMouseIndex), ItemBorderColor);
                    }

                }
                else
                {
        
                    FillItemBackColor(g, GetItemRectangle(LastMouseIndex), ItemSelectColor);
                    DrawMyItemText(g, GetItemRectangle(LastMouseIndex), LastMouseIndex);
                  
                    if (IsShowItemBorder)
                    {
                        DrawItemBorder(g, GetItemRectangle(LastMouseIndex),ItemBorderColor);

           
                    }
                }

    
                FillItemBackColor(g, GetItemRectangle(MouseIndex), ItemMouseOnColor);
                DrawMyItemText(g, GetItemRectangle(MouseIndex), MouseIndex);
                if (IsShowItemBorder)
                {
                    DrawItemBorder(g, GetItemRectangle(MouseIndex), ItemMouseOnBorderColor);
      
                }
            
          
            }
           g.Dispose();
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
          //当鼠标离开控件范围后将最后一个经过的选项还原为没经过的状态
            if (MouseIndex > -1)
            {
                if (IsUseMouseOnColor)
                {        Graphics g = this.CreateGraphics();

                if (!SelectedIndices.Contains(MouseIndex))
                {
                  FillItemBackColor(g, GetItemRectangle(MouseIndex), ItemBackColor);
                    DrawMyItemText(g, GetItemRectangle(MouseIndex), MouseIndex);
                        if (IsShowItemBorder)
                        {
                            DrawItemBorder(g,GetItemRectangle(MouseIndex), ItemBorderColor);
                        }

                    }
                else
                {
                
                        FillItemBackColor(g, GetItemRectangle(MouseIndex), ItemSelectColor);
                       DrawMyItemText(g, GetItemRectangle(MouseIndex), MouseIndex);
                        if (IsShowItemBorder)
                        {
                            DrawItemBorder(g, GetItemRectangle(MouseIndex), ItemSelectedBorderColor);
                        }
                       
                }

                g.Dispose();

                }
        

                MouseIndex = -1;
                LastMouseIndex = -1;

            }
        }
        GraphicsPath   GetItemDrawFillpath(Rectangle itemRect)
        {
            GraphicsPath Path = new GraphicsPath();
            int nowitemborderWidth = 0;
            if (IsShowItemBorder)
            {
                nowitemborderWidth = ItemBorderWidth;
            }

            switch (MyItemBorderShape)
            {
                case ItemBorderShape.RoundRectange:
                   Path = DrawHelper.GetRoundRectangePath(itemRect, nowitemborderWidth, ItemRadius);
                    break;
                case ItemBorderShape.Rectange:
                    Path = DrawHelper.GetRectangePath(itemRect, nowitemborderWidth);
                    break;
                case ItemBorderShape.TwoHalfCirclRectange:
              Path = DrawHelper.GetTwoHalfCircleRect(itemRect, nowitemborderWidth);
                    break;
                default:
                Path = DrawHelper.GetRectangePath(itemRect, nowitemborderWidth);
                  
                    break;
          
            }
            //else
            //{
                  
            //        Path.AddRectangle(itemRect);
            //}
            return Path;

        }

        void FillItemBackColor(Graphics Myg,Rectangle ItemRect,Color NowitemFillColor)
        {
            GraphicsPath NowItemFillPath = GetItemDrawFillpath(ItemRect);
            if (NowItemFillPath != null)
            {
                using (SolidBrush brush = new SolidBrush(NowitemFillColor))
                {
                    Myg.FillPath(brush, NowItemFillPath);
                }
            }
            else return;
        }
        void DrawItemBorder(Graphics Myg,Rectangle ItemRect,Color itemBorderColor)
        {

         GraphicsPath    NowItemDrawPath=GetItemDrawFillpath(ItemRect);

            if (NowItemDrawPath != null)
            {
              
                using (Pen itemborderPen = new Pen(itemBorderColor, ItemBorderWidth))
                {

                    Myg.DrawPath(itemborderPen, NowItemDrawPath);

                }
            }
            else return;
        }
        void DrawMyItemText(Graphics g,Rectangle NowItmeRect,int itemindex)
        {
            Rectangle ItemTextRect = new Rectangle();
            if (IsShowItemBorder)
            {
                ItemTextRect.X = NowItmeRect.X + (int)ItemBorderWidth;
                ItemTextRect.Y=NowItmeRect.Y+ (int)ItemBorderWidth;
                ItemTextRect.Width = NowItmeRect.Width - ItemBorderWidth * 2;
                ItemTextRect.Width = ItemTextRect.Width > 0 ? ItemTextRect.Width : 0;
                
                ItemTextRect.Height=NowItmeRect.Height- ItemBorderWidth * 2;
                ItemTextRect.Height = ItemTextRect.Height > 0 ? ItemTextRect.Height : 0;

            }
            else
            {
                ItemTextRect = NowItmeRect;
            }
            StringFormat sf = new StringFormat();
            sf.LineAlignment=StringAlignment.Center;
            switch (MyItemTextDec)
            {
                case ItemTextDec.center:
                      sf.Alignment = StringAlignment.Center;
                    break;
                case ItemTextDec.left:
                    sf.Alignment = StringAlignment.Near;
                    break;
                case ItemTextDec.right:
                    sf.Alignment = StringAlignment.Far;
                    break;
                default:
                    sf.Alignment = StringAlignment.Center;
                    break;
            }
            if (itemindex>-1)
            {
        using (SolidBrush FontBrush = new SolidBrush(ItemTextColor))
            {
                    g.DrawString(GetItemText(Items[itemindex]), Font, FontBrush, ItemTextRect, sf);

                }
            }

        }

        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);
           //鼠标双击取消选定项目
            int nowIndex = -1;
            nowIndex = this.IndexFromPoint(e.Location);
            if (nowIndex>-1&&SelectedItems.Count>0)
            {
                if (GetSelected(nowIndex))
                {
                    SetSelected(nowIndex,false);
                }
            }

        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////////
    }
}
